package client.ui;

import client.network.BanchoClient;
import common.Callback;
import common.enums.EndpointType;
import common.enums.RequestType;
import common.requests.Request;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.scene.control.Label;
import javafx.stage.Stage;

import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;

public class textUIControlller implements Initializable,ControlledStage, Callback{
    stageController theStageController;                //舞台控制器

    public long uid;
    public EndpointType type = EndpointType.User;
    public void setEndpointType(EndpointType value) {
        type = value;
    }

    public void setUid(long value) {
        uid = value;
        BanchoClient.addCallback(this);
    }
    public void setUsername(String username) {
        friendName = username;
        friendNamebt.setText(username);
    }

    @FXML
    private Button friendNamebt;     //对方用户名
    private String friendName;//从服务器得到对方用户名
    @FXML
    private Button historyMessagebt;
    @FXML
    private Button sendMessagebt;
    @FXML
    private TextArea messageField;
    @FXML
    private Rectangle rect;
    private int messageIndex = -1;
    private int maxIndex = 20;

    @FXML
    private Label tips;
    @FXML
    private ListView<String> list = new ListView<String>();
    private String[] messageBox = new String[maxIndex];
    private String[] getMessageBox;
    private String[] date;
    private boolean isClicked = false;

    /*----------------------------------------------实现接口函数----------------------------------------*/
    public void setStageController(stageController stageController){
        theStageController = stageController;
    }

    //创建要操作的文件路径和名称
    //其中，File.separator表示系统相关的分隔符，Linux下为：/  Windows下为：\\
    protected String path ="./TTmemory.txt";

    //由于IO操作会抛出异常，因此在try语句块的外部定义FileWriter的引用
    protected FileWriter w = null;

    @FXML
    @Override
    //--------------------初始化焦点在文本发送框--------
    public void initialize(URL location, ResourceBundle resources) {
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                messageField.requestFocus();
                friendNamebt.setText(friendName);


            }
        });
        messageField.setWrapText(true);
        messageField.setMaxWidth(rect.getWidth());


    }


    //点击用户名
    public void Data(MouseEvent mouseEvent) {
        //弹出好友资料
        //-------------页面跳转---------------
    }

    //弹出历史消息记录
    public void history() {
        //-------------页面跳转------------
        FXMLLoader loading = new FXMLLoader(getClass().getResource("/ui/historyUI.fxml"));
        Pane tempPane = null;
        try {
            tempPane = loading.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Scene tempScene = new Scene(tempPane);
        Stage tempStage = new Stage();
        tempStage.setResizable(false);
        tempStage.setScene(tempScene);

        tempStage.show();

    }


    //发送消息
    public void send() {
        //--------------给服务器发送消息---------

        settings(messageField.getText(), true);//若为true则为发送消息
        Map<String, Object> map = new HashMap<>();
        map.put("target", uid);
        map.put("targetType", type.toString());
        map.put("useEscape", false);
        map.put("content", messageField.getText());
        BanchoClient.SendRequest(RequestType.Message, map);
        messageField.clear();
        messageField.setEditable(true);
        messageField.requestFocus();
    }

    //----------Enter键也能控制消息发送---------------------------------
    //messageField的keyPress事件
    public void onEnter(KeyEvent event) {
        if (event.getCode() == KeyCode.ENTER)
            send();
    }


    //接收消息
    public void receive(String message) {
//-----------------------------接收服务器消息并截取对方消息内容存为String类型的message---------------------
        settings(message,false);//若为false则为接受消息
    }


    //以下为设置“更多消息”的样式
    //tips的MouseMove事件

    public void onTips(MouseEvent mouseEvent) {
        if (isClicked) {
            tips.setStyle("-fx-text-fill: darkmagenta;-fx-underline: true");
        } else
            tips.setStyle("-fx-text-fill: dodgerblue;-fx-underline: true");

    }

    //tips的MouseExited事件
    public void onTipsExited(MouseEvent mouseEvent) {
        if (isClicked) {
            tips.setStyle("-fx-text-fill: darkmagenta;-fx-underline: false");
        } else
            tips.setStyle("-fx-text-fill: dodgerblue;-fx-underline: false");
    }

    //tips的MouseClicked事件
    public void onTipsClicked(MouseEvent mouseEvent) {
        isClicked = true;
        history();//转到查看消息记录函数

    }


    //设置显示内容与格式
    //并且保存聊天记录
    public void settings(String ms, boolean flag) {
        messageIndex++;


        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        date = new String[messageIndex + 1];
        date[messageIndex] = df.format(new Date());

        ObservableList<String> message;
        if (messageIndex < maxIndex) {
            if (flag) {
                messageBox[messageIndex] = date[messageIndex] + '\n' + "我：  " + ms;
                saveMessage(messageBox[messageIndex]);
            } else {

                messageBox[messageIndex] = date[messageIndex] + '\n' +friendName+ "：  " + ms;
                saveMessage(messageBox[messageIndex]);
            }
            int cell = 0;

            for (int i = 0; i < maxIndex; i++) {
                if (messageBox[i] == null) {
                    cell = i;
                    break;
                } else cell = maxIndex;
            }
            getMessageBox = new String[cell];
            for (int i = 0; i < cell; i++) {
                getMessageBox[i] = messageBox[i];
            }
            message = FXCollections.observableArrayList(getMessageBox);
        } else {
            for (int i = 0; i < maxIndex - 1; i++) {
                messageBox[i] = messageBox[i + 1];
            }
            if (flag) {
                messageBox[maxIndex - 1] = date[messageIndex] + '\n' + "我：  " + ms;
                saveMessage(messageBox[maxIndex - 1] );
            } else {

                messageBox[maxIndex - 1] = date[messageIndex] + '\n' + friendName+"：  " + ms;
                saveMessage(messageBox[maxIndex - 1] );

            }

            message = FXCollections.observableArrayList(messageBox);

        }

        list.setItems(message);

        if (messageIndex == maxIndex) {
            tips.setText("更多消息请查看消息记录...");
            tips.setStyle("-fx-text-fill: dodgerblue");
            tips.setVisible(true);
        }
    }

    //保存聊天记录
    public void saveMessage(String saveMs){
        try {
            //以path为路径创建一个新的FileWriter对象
            //如果需要追加数据，而不是覆盖，则使用FileWriter（path，true）构造方法
            w = new FileWriter(path,true);

            //将字符串写入到流中，\r\n表示换行想有好的
            w.write(saveMs+"\r\n");
            //如果想马上看到写入效果，则需要调用w.flush()方法
            w.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //如果前面发生异常，那么是无法产生w对象的
            //因此要做出判断，以免发生空指针异常
            if(w != null) {
                try {
                    //关闭流资源，需要再次捕捉异常
                    w.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    @Override
    public void callback(Request request) {
        Platform.runLater(() -> {
            if (request.type == RequestType.Message) {
                if (Objects.equals(request.payload.get("containerType").toString(), String.valueOf(EndpointType.Group))) {
                    friendName = request.payload.get("senderName").toString();
                }
                receive(request.payload.get("content").toString());

            }
        });
    }

}